#define	ACFANDRV_C	

#include "Global.h"


#define	C_FAN_SETION_OFF			(0)	//空闲状态
#define	C_FAN_SETION_1stDRV			(1)	//脉冲输出1
#define	C_FAN_SETION_1stSTOP		(2) //脉冲停止1
#define	C_FAN_SETION_2stDRV			(3) //脉冲输出2
#define	C_FAN_SETION_2stSTOP		(4) //脉冲停止2

//最高滤波转速下 CAL_PER_TURN 圈数的最短时间
#define FAN_FILTER_TIME         (60000000u/FAN_FILT_SPEED/FAN_TIMER_RATE*CAL_PER_TURN)      // 风速反馈滤波时间，单位us.


typedef struct _TYPE_DC_FAN
{
	unsigned short u16_aimSpeed;		//目标转速
	unsigned short u16_curSpeed;		//实际转速
	unsigned short u16_speedTime;	//转速采样时间
	unsigned short u16_timeCnt;		//中断计时
	unsigned char u8_pidAdjTime;			//PID计算间隔
	unsigned char u8_errCnt;				//故障计数
	unsigned char u8_pulseCnt;				//转速反馈计数
}TYPE_PG_FAN;



TYPE_PG_FAN  InFan = {0};
unsigned char  u8_zeroIntCnt = 0; 		//过零计时
unsigned char  u8_zeroTime = 0;   		//过零点脉冲时间
unsigned short u16_pwidthFinal = 0;
unsigned char u8_fanDrvSetion = 0;

unsigned short u16_zeroCycleTime = 1000000/ZERO_DEFAULT_FRE/2;//单位us 脉冲宽度


signed short CalPID(signed short s16_trigetVal,signed short s16_curVal, char s8_initFlag)
{
	static signed short s16_p_Val = 0;
	static signed short s16_i_Val = 0;
	static signed short s16_d_Val = 0;
	static signed short s16_last_P = 0;
	static signed short s16_last_I = 0;
	signed long s32_temp = 0;

	if(s8_initFlag)
	{
		s16_p_Val = 0;
		s16_i_Val = 0;
		s16_d_Val = 0;
		s16_last_P = 0;
		s16_last_I = 0;
	}
	else
	{
		s16_last_P = s16_p_Val;
		s16_p_Val = s16_trigetVal - s16_curVal;
		s16_last_I = s16_i_Val;
		s16_i_Val = s16_p_Val - s16_last_P;
		s16_d_Val = s16_i_Val - s16_last_I;
		s32_temp = ((signed long)s16_p_Val * PID_P);
		s32_temp += ((signed long)s16_i_Val * PID_I);
		s32_temp += ((signed long)s16_d_Val * PID_D);
	}
	return (signed short)s32_temp;
}

void PIDAdjust(void)
{
	signed short s16_temp = 0;
	static unsigned short u16_pWidth = 0;
	
	if(InFan.u16_aimSpeed == 0)
	{
		CalPID(0,0,1);
		u16_pWidth = MIN_PWM_TIM;
		if(GetTimeTick(TIME_100ms))SaveVisualData(InFan.u16_curSpeed,u16_pWidth,0,0);
	}
	else
	{
		if(GetTimeTick(TIME_10ms))
		{
			if(InFan.u8_pidAdjTime)InFan.u8_pidAdjTime --;
		}
		if(InFan.u8_pidAdjTime == 0)
		{
			InFan.u8_pidAdjTime = 20;
			s16_temp = CalPID(InFan.u16_aimSpeed,InFan.u16_curSpeed,0);
			if(s16_temp > MAX_ADJ_VAL)s16_temp = MAX_ADJ_VAL;
			else if(s16_temp < (-MAX_ADJ_VAL))s16_temp = -MAX_ADJ_VAL; 
			u16_pWidth -= s16_temp;
			if(u16_pWidth > MAX_PWM_TIM)u16_pWidth = MAX_PWM_TIM;
			else if(u16_pWidth < MIN_PWM_TIM)u16_pWidth = MIN_PWM_TIM;
			SaveVisualData(InFan.u16_curSpeed,u16_pWidth,0,0);
		}
	}
	u16_pwidthFinal = u16_pWidth;
}

/**************************************************************
//Fuction Name: F_ZeroINT(void)
//Desrition:单相 过零检测中断
//Input: 
//Output: 
//Author:陈首敏
//Date:2014.12.1
***************************************************************/
void ZeroINT(void) //外部中断
{
	if(u8_zeroIntCnt >= (4000/FAN_TIMER_RATE))// 20150421_2 加入过零防干扰脉冲对策 略小于1/f/2
	{
		u8_zeroTime = u8_zeroIntCnt;
		u8_zeroIntCnt = 0;
		if(0 == PI_ZERO) //检测下降沿过零信号
		{
			PutLowFanDrivePin();
			if(InFan.u16_aimSpeed == 0)
			{
				DisableTimerInt();	// 关闭定时器
				StopTimer();
				u8_fanDrvSetion = C_FAN_SETION_OFF;
			}
			else
			{
				SetTimerIntTime(u16_pwidthFinal);
				EnableTimerInt();	
				StarTimer();			
				ClrTimerIntFlag();		
				u8_fanDrvSetion = C_FAN_SETION_1stDRV;//风机驱动阶段
			}	
		}
	}
}

void ZeroCal()
{
	static unsigned short u16_zeroSum = 0;
	static unsigned char u8_zeroCnt = 0;
	
	if(u8_zeroTime)
	{
		u16_zeroSum += u8_zeroTime;
		u8_zeroTime = 0;
		u8_zeroCnt ++;
		if(u8_zeroCnt >= 64) //64个过零点计算一次过零周期
		{
			u8_zeroCnt = 0;
			u16_zeroCycleTime = (u16_zeroSum + 32) >> 6;
			u16_zeroCycleTime = u16_zeroCycleTime * FAN_TIMER_RATE /(ZERO_DETECC_TYPE + 1);
			if((u16_zeroCycleTime > (1000000/ZERO_MIN_FRE/2))
			||(u16_zeroCycleTime < (1000000/ZERO_MAX_FRE/2)))
			{
				u16_zeroCycleTime = 1000000/ZERO_DEFAULT_FRE/2;
			}
			u16_zeroSum = 0;
		}
	}
}
/**************************************************************
//Fuction Name: F_ACFanDriveINT(void)
//Desrition: 风机驱动中断
//Input: 
//Output: 
//Author:陈首敏
//Date:2014.12.1
***************************************************************/
void ACFanDriveINT(void)
{
	if(C_FAN_SETION_1stDRV == u8_fanDrvSetion)
	{
		u8_fanDrvSetion = C_FAN_SETION_1stSTOP;
		PutHighFanDrivePin();		
		SetTimerIntTime(FAN_DRV_PULSE_WIDTH);// 脉冲宽度500us
		EnableTimerInt();				
		StarTimer();			
		ClrTimerIntFlag();
	}
	else if(C_FAN_SETION_1stSTOP == u8_fanDrvSetion)
	{
		if(ZERO_DETECC_TYPE == 0)
		{
			u8_fanDrvSetion = C_FAN_SETION_OFF;
			PutLowFanDrivePin();
			SetTimerIntTime(0);
			DisableTimerInt();			
			StopTimer();	
			ClrTimerIntFlag();
		}
		else
		{
			u8_fanDrvSetion = C_FAN_SETION_2stDRV;
			PutLowFanDrivePin();		
			SetTimerIntTime(u16_zeroCycleTime - FAN_DRV_PULSE_WIDTH);// 脉冲宽度500us
			EnableTimerInt();				
			StarTimer();			
			ClrTimerIntFlag();
		}
	}
	else if(C_FAN_SETION_2stDRV == u8_fanDrvSetion)
	{
		u8_fanDrvSetion = C_FAN_SETION_2stSTOP;
		PutHighFanDrivePin();		
		SetTimerIntTime(FAN_DRV_PULSE_WIDTH);	// 脉冲宽度500us
		EnableTimerInt();				
		StarTimer();			
		ClrTimerIntFlag();
	}
	else 
	{
		u8_fanDrvSetion = C_FAN_SETION_OFF;
		PutLowFanDrivePin();		
		SetTimerIntTime(0);
		DisableTimerInt();				
		StopTimer();	
		ClrTimerIntFlag();
	}
}


void InFanBckIRQ()//125us时钟中断
{
	static unsigned char  u8_inFanBckFilter = 0;
	static unsigned char  u8_highFlag = 0;
	
	if(InFan.u16_timeCnt < 0xffff)InFan.u16_timeCnt ++;
	u8_inFanBckFilter <<= 1;
	if(PI_FB)u8_inFanBckFilter |= 0x01;
	if(u8_inFanBckFilter == b1111_1111)
	{
		u8_highFlag = 1;
	}
	if(u8_highFlag)
	{
		if(u8_inFanBckFilter == b1000_0000)
		{
			u8_highFlag = 0;
			InFan.u8_pulseCnt ++;
			if((InFan.u8_pulseCnt >= PLUSE_PER_CYCLE*CAL_PER_TURN)&&(InFan.u16_timeCnt > FAN_FILTER_TIME))
			{
				if(InFan.u16_speedTime == 0)InFan.u16_speedTime = InFan.u16_timeCnt;
				InFan.u8_pulseCnt = 0;
				InFan.u16_timeCnt = 0;
			}
		}
	}
	if(u8_zeroIntCnt != 0xff)u8_zeroIntCnt ++;
}

void GetCurFan(void)
{
	if(InFan.u16_timeCnt == 0xffff)
	{
		InFan.u16_curSpeed = 0;
		InFan.u8_pulseCnt = 0;
		InFan.u16_timeCnt = 0;
	}
	else
	{
		if(InFan.u16_speedTime)
		{
			InFan.u16_curSpeed = (unsigned short)((60000000u*CAL_PER_TURN/FAN_TIMER_RATE)/(u32)(InFan.u16_speedTime));
			InFan.u16_speedTime = 0;
			InFan.u8_pidAdjTime = 0;
		}
	}
}

void FanCheckError(void)
{
	if(InFan.u16_aimSpeed)
	{
		if(InFan.u16_curSpeed < FAN_MIN_SPEED)
		{
			if(GetTimeTick(TIME_1s))
			{
				if(InFan.u8_errCnt < 30)
					InFan.u8_errCnt ++;
				else
					SysInfo.Err.FanErr = 1;
			}
		}
		else
		{
			InFan.u8_errCnt = 0;
			SysInfo.Err.FanErr = 0;
		}
	}
	else
	{
		InFan.u8_errCnt = 0;
		if(SysSet.fg.TurnOn == 0)SysInfo.Err.FanErr = 0;
	}
}

void FanDrv(void)
{
	GetCurFan();
	PIDAdjust();
	ZeroCal();
	FanCheckError();
}

